package com.queclink.md5;

public class Quec_MD5 {
    long[] groups = null;
    static final long A = 412501297L;
    static final long B = 1454103806L;
    static final long C = 2280635085L;
    static final long D = 629577828L;
    static final long[][] T = new long[][]{{-680876936L, -389564586L, 606105819L, -1044525330L, -176418897L, 1200080426L, -1473231341L, -45705983L, 1770035416L, -1958414417L, -42063L, -1990404162L, 1804603682L, -40341101L, -1502002290L, 1236535329L}, {-165796510L, -1069501632L, 643717713L, -373897302L, -701558691L, 38016083L, -660478335L, -405537848L, 568446438L, -1019803690L, -187363961L, 1163531501L, -1444681467L, -51403784L, 1735328473L, -1926607734L}, {-378558L, -2022574463L, 1839030562L, -35309556L, -1530992060L, 1272893353L, -155497632L, -1094730640L, 681279174L, -358537222L, -722521979L, 76029189L, -640364487L, -421815835L, 530742520L, -995338651L}, {-198630844L, 1126891415L, -1416354905L, -57434055L, 1700485571L, -1894986606L, -1051523L, -2054922799L, 1873313359L, -30611744L, -1560198380L, 1309151649L, -145523070L, -1120210379L, 718787259L, -343485551L}};
    static final int[][] k = new int[][]{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, {1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12}, {5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2}, {0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9}};
    static final int[][] S = new int[][]{{7, 12, 17, 22}, {5, 9, 14, 20}, {4, 11, 16, 23}, {6, 10, 15, 21}};

    public Quec_MD5() {
    }

    private static long g(int paramInt, long paramLong1, long paramLong2, long paramLong3) {
        switch(paramInt) {
            case 0:
                return paramLong1 & paramLong2 | ~paramLong1 & paramLong3;
            case 1:
                return paramLong1 & paramLong3 | paramLong2 & ~paramLong3;
            case 2:
                return paramLong1 ^ paramLong2 ^ paramLong3;
            case 3:
                return paramLong2 ^ (paramLong1 | ~paramLong3);
            default:
                return 0L;
        }
    }

    public static String start(String paramString) {
        byte[] arrayOfByte1 = paramString.getBytes();
        String resultMessage = "";
        long[] result = new long[]{412501297L, 1454103806L, 2280635085L, 629577828L};
        int i = arrayOfByte1.length;
        long l = (long)(i << 3);
        int j = i / 64;

        int k;
        for(k = 0; k < j; ++k) {
            H(divide(arrayOfByte1, k * 64), result);
        }

        k = i % 64;
        byte[] arrayOfByte2 = new byte[64];

        int m;
        for(m = 0; m < k; ++m) {
            arrayOfByte2[m] = arrayOfByte1[i - k + m];
        }

        if (k <= 55) {
            if (k <= 55) {
                arrayOfByte2[k] = -128;

                for(m = 1; m < 56 - k; ++m) {
                    arrayOfByte2[k + m] = 0;
                }
            }

            for(m = 0; m < 8; ++m) {
                arrayOfByte2[56 + m] = (byte)((int)(l & 255L));
                l >>= 8;
            }

            H(divide(arrayOfByte2, 0), result);
        } else {
            arrayOfByte2[k] = -128;

            for(m = k + 1; m < 64; ++m) {
                arrayOfByte2[m] = 0;
            }

            H(divide(arrayOfByte2, 0), result);

            for(m = 0; m < 56; ++m) {
                arrayOfByte2[m] = 0;
            }

            for(m = 0; m < 8; ++m) {
                arrayOfByte2[56 + m] = (byte)((int)(l & 255L));
                l >>= 8;
            }

            H(divide(arrayOfByte2, 0), result);
        }

        for(m = 0; m < 4; ++m) {
            resultMessage = resultMessage + String.format("%02x", result[m] & 255L) + String.format("%02x", (result[m] & 65280L) >> 8) + String.format("%02x", (result[m] & 16711680L) >> 16) + String.format("%02x", (result[m] & -16777216L) >> 24);
        }

        return resultMessage;
    }

    private static long[] divide(byte[] paramArrayOfbyte, int paramInt) {
        long[] arrayOfLong = new long[16];

        for(byte b = 0; b < 16; ++b) {
            arrayOfLong[b] = byte2unsign(paramArrayOfbyte[4 * b + paramInt]) | byte2unsign(paramArrayOfbyte[4 * b + 1 + paramInt]) << 8 | byte2unsign(paramArrayOfbyte[4 * b + 2 + paramInt]) << 16 | byte2unsign(paramArrayOfbyte[4 * b + 3 + paramInt]) << 24;
        }

        return arrayOfLong;
    }

    public static long byte2unsign(byte paramByte) {
        return paramByte < 0 ? (long)(paramByte & 255) : (long)paramByte;
    }

    private static void H(long[] paramArrayOflong, long[] result) {
        long l1 = result[0];
        long l2 = result[1];
        long l3 = result[2];
        long l4 = result[3];

        byte b;
        for(b = 0; b < 4; ++b) {
            for(byte b1 = 0; b1 < 16; ++b1) {
                result[0] = result[0] + (g(b, result[1], result[2], result[3]) & 4294967295L) + paramArrayOflong[k[b][b1]] + T[b][b1];
                result[0] = result[1] + ((result[0] & 4294967295L) << S[b][b1 % 4] | (result[0] & 4294967295L) >>> 32 - S[b][b1 % 4]);
                long l = result[3];
                result[3] = result[2];
                result[2] = result[1];
                result[1] = result[0];
                result[0] = l;
            }
        }

        result[0] += l1;
        result[1] += l2;
        result[2] += l3;
        result[3] += l4;

        for(b = 0; b < 4; ++b) {
            result[b] &= 4294967295L;
        }

    }
}
